package com.bestcem.xm.txtanls.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.oss.enums.OssPathEnum;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.txtanls.config.TxtanlsFileConfig;
import com.bestcem.xm.txtanls.controller.vo.DownloadRecordVO;
import com.bestcem.xm.txtanls.controller.vo.excel.DownloadDataVO;
import com.bestcem.xm.txtanls.dao.*;
import com.bestcem.xm.txtanls.dao.dto.PageDTO;
import com.bestcem.xm.txtanls.entity.pojo.*;
import com.bestcem.xm.txtanls.enums.EmotionKeyEnum;
import com.bestcem.xm.txtanls.enums.ViewpointTypeEnum;
import com.bestcem.xm.txtanls.grpc.service.param.PageParam;
import com.bestcem.xm.txtanls.grpc.service.param.record.DownloadRecordParam;
import com.bestcem.xm.txtanls.grpc.service.param.record.ListRecordParam;
import com.bestcem.xm.txtanls.grpc.service.param.record.QueryConditionParam;
import com.bestcem.xm.txtanls.grpc.service.param.record.RecordTopicRelationParam;
import com.bestcem.xm.txtanls.service.RecordService;
import com.bestcem.xm.txtanls.service.dto.RecordSearchDTO;
import com.bestcem.xm.txtanls.service.dto.chart.PeriodTimeDTO;
import com.bestcem.xm.txtanls.service.dto.chart.TimeRangeDTO;
import com.bestcem.xm.txtanls.service.dto.record.*;
import com.bestcem.xm.txtanls.util.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.bestcem.xm.common.core.constant.Constants.*;
import static com.bestcem.xm.txtanls.util.FileUtils.FILE_PATH;


/**
 * 原话service实现类
 *
 * @author liheng
 * @version v1.0
 * @date 2021/5/10-17:24
 */
@Slf4j
@Service
public class RecordServiceImpl implements RecordService {
    /**
     * 临时存储目录
     */
    private static final String UPLOAD_REMARK = "【txtanls】原话记录上传";

    /**
     * oss文件过期时间，暂定3分钟
     */
    private static final long OSS_FILE_EXPIRE_SECONDS = 3 * 60;


    /**
     * 未导出数据，提示信息
     */
    private static final String EXPORT_NULL = "未导出任何数据";


    @Resource
    private RecordDao recordDao;
    @Resource
    private AnalysisProjectDao analysisProjectDao;
    @Resource
    private TopicDao topicDao;
    @Resource
    private JoinInfoDao joinInfoDao;
    /*@Resource
    private OssService ossService;*/

    @Value("${app.txtanls.record.file-dir:classpath:data}")
    private String fileDir;

    @Resource
    private TxtanlsFileConfig txtanlsFileConfig;

    @Resource
    private ViewpointDao viewpointDao;

    @Resource
    private SurveyTxtanlsFieldDao surveyTxtanlsFieldDao;

    @Autowired
    private StorageService storageService;

    @Override
    public ServiceResult<RecordTopicRelationDTO> getRecordTopicRelation(RecordTopicRelationParam param) {
        String projectId = param.getProjectId();
        TimeRangeDTO timeRangeDTO = param.getTimeRangeDTO();
        String fieldId = param.getFieldId();
        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
            return ServiceResult.fail("fieldId错误");
        }
        List<String> fieldIds = analysisProjectDao.listTextFiledId(projectId, fieldId);
        Set<String> keywords = topicDao.listTopicKeyword(projectId);
        RecordSearchDTO searchCondition = new RecordSearchDTO(projectId, fieldIds, timeRangeDTO.getPeriodTime());
        // 原话记录总数
        long totalCount = recordDao.countRecord(searchCondition);
        if (keywords == null) {
            keywords = new HashSet<>();
        }
        searchCondition.setKeywords(new ArrayList<>(keywords));

        // 匹配关键词的原话数
        long recordKeywordsCount = recordDao.countRecord(searchCondition);
        RecordTopicRelationDTO recordTopicRelationDTO = new RecordTopicRelationDTO(recordKeywordsCount, totalCount - recordKeywordsCount);
        return ServiceResult.success(recordTopicRelationDTO);
    }

    @Override
    public ServiceResult<LocalDateTime> getRecordMaxTime(String projectId) {
        // 查询最大的recordtime
        LocalDateTime maxTime;
        try {
            maxTime = recordDao.getMaxTime(projectId);
        } catch (Exception dateTimeParseException) {
            log.error("[]原话数据解析出错,文本分析项目id:{}", projectId);
            maxTime = LocalDateTime.now().minusDays(ONE);
        }

        if (ObjectUtils.isEmpty(maxTime)) {
            // 如果无记录，则返回昨天
            maxTime = LocalDateTime.now().minusDays(ONE);
        }
        return ServiceResult.success(maxTime);
    }

    @Override
    public ServiceResult<ListRecordDTO> listRecord(ListRecordParam param) {
        QueryConditionParam queryParam = param.getQueryParam();
        String projectId = queryParam.getProjectId();
        PageParam pageParam = param.getPageParam();
        TimeRangeDTO timeRangeParam = param.getTimeRangeDTO();
        String fieldId = queryParam.getFieldId();
        String topicId = queryParam.getTopicId();
        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
            return ServiceResult.fail("filedId参数错误");
        }
        if (StringUtils.isNotBlank(topicId) && !ObjectId.isValid(topicId)) {
            return ServiceResult.fail("topicId格式错误");
        }
        // 构造查询条件
        PageRecordDTO queryCondition = this.genQueryCondition(queryParam, timeRangeParam, pageParam);
        if (Objects.isNull(queryCondition)) {
            return ServiceResult.success(new ListRecordDTO(new PageDTO<>(Collections.emptyList(), LONG_ZERO),
                    new PageParam(pageParam.getPage(), pageParam.getSize())));
        }
        // 分页查询原话
        PageDTO<RecordDO> pageData = recordDao.pageRecord(queryCondition);
        if (CollUtil.isEmpty(pageData.getData())) {
            return ServiceResult.success(new ListRecordDTO(new PageDTO<>(Collections.emptyList(), pageData.getTotal()),
                    new PageParam(pageParam.getPage(), pageParam.getSize())));
        }
        // 转换展示dto，内部会查join_info表填充数据
        List<RecordDetailDTO> recordDetailDTOS = entityToDetailList(pageData, queryCondition.getTopicInfo(), projectId);
        PageDTO<RecordDetailDTO> recordDetailDTOPageDTO = new PageDTO<>(recordDetailDTOS, pageData.getTotal());
        return ServiceResult.success(new ListRecordDTO(recordDetailDTOPageDTO, pageParam));
    }

    @Override
    public ServiceResult<DownloadRecordDTO> downloadRecord(DownloadRecordParam downloadRecordParam) {
        QueryConditionParam queryParam = downloadRecordParam.getQueryParam();
        String fieldId = queryParam.getFieldId();
        String topicId = queryParam.getTopicId();
        DownloadRecordDTO downloadRecordDTO = new DownloadRecordDTO();
        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
            return ServiceResult.fail("filedId参数错误");
        }
        if (StringUtils.isNotBlank(topicId) && !ObjectId.isValid(topicId)) {
            return ServiceResult.fail("topicId格式错误");
        }
        PageRecordDTO queryCondition = this.genQueryCondition(queryParam, downloadRecordParam.getTimeRangeDTO(), null);
        if (Objects.isNull(queryCondition)) {
            return ServiceResult.success(downloadRecordDTO, "未导出任何数据");
        }

        // 不分页查询全部原话数据
        PageDTO<RecordDO> pageData = recordDao.pageRecord(queryCondition);
        List<RecordDO> data = pageData.getData();
        if (CollUtil.isEmpty(data)) {
            // 查询为空，直接返回
            return ServiceResult.success(downloadRecordDTO, "未导出任何数据");
        }
        List<ExportRecordDTO> excelData = new ArrayList<>(data.size());
        for (RecordDO recordDO : data) {
            String content = recordDO.getContent();
            String emotionName = ObjectUtil.isEmpty(recordDO.getSenti()) ? null : EmotionKeyEnum.getKeyByIndex(recordDO.getSenti());
            String fieldName = recordDO.getFieldName();
            String recordTime = recordDO.getRecordTime();
            // 判断原话，情感，字段名，原话时间都为空则跳过
            if (ObjectUtil.isAllEmpty(content, emotionName, fieldName, recordTime)) {
                continue;
            }
            excelData.add(new ExportRecordDTO(content, emotionName, recordDO.getFieldName(), recordTime));
        }

        if (CollUtil.isEmpty(excelData)) {
            return ServiceResult.success(downloadRecordDTO, "未导出任何数据");
        }
        // 生成excel文件，上传到OSS
        ProjectDO projectEntity = analysisProjectDao.findById(queryCondition.getProjectId());
        String fileName = projectEntity.getName() + HYPHEN + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss")) + "." + XLSX_SUFFIX;
        String path = FILE_PATH + File.separator + fileDir + File.separator + fileName;
        File file = FileUtils.creatRecordExcel(excelData, path);
        //String url = ossService.uploadSimpleFile(file, fileName, OssPathEnum.TEMP_TXTANLS, OSS_FILE_EXPIRE_SECONDS, null, "");
        String url = storageService.upload(file, fileName, OssPathEnum.TEMP_TXTANLS.getPath(), new Dict()).getUrl();
        // 删除临时文件
        file.delete();
        return ServiceResult.success(new DownloadRecordDTO(fileName, url, XLSX_SUFFIX, file.length()));
    }


    //    @Override
//    public ServiceResult<DownloadRecordDTO> listDataForDownload(DownloadRecordParam downloadRecordParam) {
//        QueryConditionParam queryParam = downloadRecordParam.getQueryParam();
//        String fieldId = queryParam.getFieldId();
//        String topicId = queryParam.getTopicId();
//        DownloadRecordDTO downloadRecordDTO = new DownloadRecordDTO();
//        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
//            return ServiceResult.fail("filedId参数错误");
//        }
//        if (StringUtils.isNotBlank(topicId) && !ObjectId.isValid(topicId)) {
//            return ServiceResult.fail("topicId格式错误");
//        }
//        PageRecordDTO queryCondition = this.genQueryCondition(queryParam, downloadRecordParam.getTimeRangeDTO(), null);
//
//        if (Objects.isNull(queryCondition)) {
//            return ServiceResult.fail(downloadRecordDTO, EXPORT_NULL);
//        }
//        // 不分页查询全部原话数据
//        PageDTO<Record> pageData = recordDao.pageRecord(queryCondition);
//        List<Record> data = pageData.getData();
//        if (CollUtil.isEmpty(data)) {
//            // 查询为空，直接返回
//            return ServiceResult.success(downloadRecordDTO, EXPORT_NULL);
//        }
//        List<ExportRecordDTO> excelData = new ArrayList<>(data.size());
//        for (Record record : data) {
//            String content = record.getContent();
//            String emotionName = ObjectUtil.isEmpty(record.getSenti()) ? null : EmotionKeyEnum.getKeyByIndex(record.getSenti());
//            String fieldName = record.getFieldName();
//            String recordTime = record.getRecordTime();
//            // 判断原话，情感，字段名，原话时间都为空则跳过
//            if (ObjectUtil.isAllEmpty(content, emotionName, fieldName, recordTime)) {
//                continue;
//            }
//            excelData.add(new ExportRecordDTO(content, emotionName, record.getFieldName(), recordTime));
//        }
//
//        if (CollUtil.isEmpty(excelData)) {
//            return ServiceResult.success(downloadRecordDTO, EXPORT_NULL);
//        }
//        AnalysisProject projectEntity = analysisProjectDao.findById(queryCondition.getProjectId());
//        String fileName = projectEntity.getName() + HYPHEN + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss")) + "." + XLSX_SUFFIX;
//        return ServiceResult.success(new DownloadRecordDTO(fileName, null, XLSX_SUFFIX, null, excelData));
//    }
//
//
    @Override
    public ServiceResult<DownloadRecordVO> downloadRecordForHttp(DownloadRecordParam downloadRecordParam) {
        QueryConditionParam queryParam = downloadRecordParam.getQueryParam();
        String fieldId = queryParam.getFieldId();
        String topicId = queryParam.getTopicId();
        DownloadRecordVO downloadRecordDTO = new DownloadRecordVO();
        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
            return ServiceResult.fail("filedId参数错误");
        }
        if (StringUtils.isNotBlank(topicId) && !ObjectId.isValid(topicId)) {
            return ServiceResult.fail("topicId格式错误");
        }
        PageRecordDTO queryCondition = this.genQueryCondition(queryParam, downloadRecordParam.getTimeRangeDTO(), null);
        if (Objects.isNull(queryCondition)) {
            return ServiceResult.success(downloadRecordDTO, "未导出任何数据");
        }

        // 不分页查询全部原话数据
        PageDTO<RecordDO> pageData = recordDao.pageRecord(queryCondition);
        List<RecordDO> data = pageData.getData();
        if (CollUtil.isEmpty(data)) {
            // 查询为空，直接返回
            return ServiceResult.success(downloadRecordDTO, "未导出任何数据");
        }
        ProjectDO projectDo = analysisProjectDao.findById(queryCondition.getProjectId());

        Map<String, String> textIdNameMap = new HashMap<>();
        if (Validator.isNotEmpty(projectDo.getSurveyId())) {
            List<ProjectFieldDO> textFieldList = projectDo.getTextFieldList();
            if (CollUtil.isNotEmpty(textFieldList)) {
                List<SurveyTxtanlsFieldDO> projectAllTextFiled = surveyTxtanlsFieldDao.findProjectAllTextFiled(projectDo.getId());
                if (CollUtil.isNotEmpty(projectAllTextFiled)) {
                    Map<String, SurveyTxtanlsFieldDO> fieldEntityMap =
                            projectAllTextFiled.stream().collect(Collectors.toMap(SurveyTxtanlsFieldDO::getId, self -> self, (prev, now) -> prev));
                    for (ProjectFieldDO textField : textFieldList) {
                        SurveyTxtanlsFieldDO entity = fieldEntityMap.get(textField.getId());
                        if (Objects.nonNull(entity)) {
                            textIdNameMap.put(textField.getId(), entity.getSurveyColName());
                        }
                    }
                }
            }
        }
        if (log.isInfoEnabled()) {
            log.info("字段映射数据:{}", textIdNameMap);
        }
        List<DownloadDataVO> excelData = new ArrayList<>(data.size());
        for (RecordDO record : data) {
            String content = record.getContent();
            String emotionName = ObjectUtil.isEmpty(record.getSenti()) ? null : EmotionKeyEnum.getKeyByIndex(record.getSenti());
            String fieldName = textIdNameMap.getOrDefault(record.getFieldId(), record.getFieldName());
            String recordTime = record.getRecordTime();
            // 判断原话，情感，字段名，原话时间都为空则跳过
            if (ObjectUtil.isAllEmpty(content, emotionName, fieldName, recordTime)) {
                continue;
            }
            excelData.add(new DownloadDataVO(content, emotionName, fieldName, recordTime));
        }
        if (CollUtil.isEmpty(excelData)) {
            return ServiceResult.success(downloadRecordDTO, "未导出任何数据");
        }
        // 生成excel文件，上传到OSS
        // 文件名判断.文件名格式为：“话题/话题组名称 + 关联原话” 使用“-”分割后取最后一个
        String fileName;
        if (Validator.isNotEmpty(queryCondition.getTopicInfo())) {
            String[] topicNameArr = queryCondition.getTopicInfo().split("-");
            fileName = topicNameArr[topicNameArr.length - 1] + "关联原话" + "." + XLSX_SUFFIX;
        } else {
            fileName = projectDo.getName() + HYPHEN + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss")) + "." + XLSX_SUFFIX;
        }
        String path = txtanlsFileConfig.getTxtanlsTempFilePath(fileName);
        File file = FileUtils.creatRecordEasyExcel(excelData, path);
        //String url = ossService.uploadTempFile(file, fileName, OssPathEnum.TEMP_TXTANLS, OSS_FILE_EXPIRE_SECONDS, file.getAbsolutePath(), UPLOAD_REMARK);
        String url = storageService.upload(file, fileName, OssPathEnum.TEMP_TXTANLS.getPath(), new Dict()).getUrl();
        if (log.isInfoEnabled()) {
            log.info("[txtanls]:生成url成功,url:{}!!", url);
        }
        // 删除临时文件
        if (StringUtils.isBlank(url)) {
            return ServiceResult.fail("导出失败");
        }
        // 删除本地生成的临时文件
        file.deleteOnExit();
        return ServiceResult.success(new DownloadRecordVO(fileName, url, XLSX_SUFFIX, file.length()));
    }

    private PageRecordDTO genQueryCondition(QueryConditionParam queryParam, TimeRangeDTO timeRangeParam, PageParam pageParam) {
        PageRecordDTO pageRecordDTO = new PageRecordDTO();
        pageRecordDTO.setPageParam(pageParam);
        // 时间封装
        if (ObjectUtils.isNotEmpty(timeRangeParam) && ObjectUtils.isNotEmpty(timeRangeParam.getPeriodTime())) {
            PeriodTimeDTO periodTime = timeRangeParam.getPeriodTime();
            pageRecordDTO.setStartTime(periodTime.getStartTime());
            pageRecordDTO.setEndTime(periodTime.getEndTime());
        }
        pageRecordDTO.setProjectId(queryParam.getProjectId());
        // 情感关键词
        if (!Objects.isNull(queryParam.getEmotion())) {
            pageRecordDTO.setSenti(queryParam.getEmotion());
        }
        // 话题信息处理
        if (StringUtils.isNotBlank(queryParam.getTopicId()) && StringUtils.isBlank(queryParam.getViewpointId())) {
            TopicDO topic = topicDao.getById(queryParam.getTopicId());
            if (CollUtil.isEmpty(topic.getKeyDict())) {
                return null;
            }
            if (ObjectUtils.isNotEmpty(topic)) {
                TopicDO topicGroup = topicDao.getById(topic.getTopicGID());
                // 话题组名-话题名
                pageRecordDTO.setTopicInfo(topicGroup.getName() + "-" + topic.getName());
            }
            pageRecordDTO.setTopicKeyword(String.join(OR, topic.getKeyDict()));
        }
        // 根据预置话题（观点过滤）
        if (StringUtils.isNotBlank(queryParam.getViewpointId()) && StringUtils.isBlank(queryParam.getTopicId())) {
            ViewpointDO viewpoint = viewpointDao.getById(queryParam.getViewpointId());
            // 观点情感得分
            Integer emotion = queryParam.getEmotion();
            Integer viewpointScore = EmotionKeyEnum.getViewpointScore(emotion);
            pageRecordDTO.setSenti(null);
            if (Objects.isNull(viewpoint)) {
                return null;
            }
            // 如果点击观点中的混合情感，不返回任何数据
            if (EmotionKeyEnum.MIX.getIndex() == emotion && ViewpointTypeEnum.CHILDREN.getIndex() == viewpoint.getType()) {
                return null;
            }
            List<String> recordIds;
            if (cn.hutool.core.lang.ObjectId.isValid(viewpoint.getGroupId())) {
                // 预置子话题查询
                ViewpointDO parentView = viewpointDao.getById(viewpoint.getGroupId());
                if (ObjectUtil.isNotNull(parentView)) {
                    pageRecordDTO.setTopicInfo(parentView.getViewContent() + "-" + viewpoint.getViewContent());
                } else {
                    pageRecordDTO.setTopicInfo(viewpoint.getViewContent());
                }
                recordIds = joinInfoDao.listIdByViewpointId(Arrays.asList(queryParam.getViewpointId()), queryParam.getProjectId(), viewpointScore, false);
            } else {
                // 预置父话题查询
                List<ViewpointDO> viewpointList = viewpointDao.listChildrenViewpoint(queryParam.getViewpointId(), queryParam.getProjectId());
                if (CollUtil.isEmpty(viewpointList)) {
                    return null;
                }
                pageRecordDTO.setTopicInfo(viewpoint.getViewContent());
                List<String> viewpointIds = viewpointList.stream().map(ViewpointDO::getId).collect(Collectors.toList());
                recordIds = joinInfoDao.listIdByViewpointId(viewpointIds, queryParam.getProjectId(), viewpointScore, true);
            }
            if (CollUtil.isEmpty(recordIds)) {
                // 观点过滤如果原话id为空，返回空
                return null;
            }
            pageRecordDTO.setRecordIds(recordIds);
        }
        List<String> fieldIds = analysisProjectDao.listTextFiledId(queryParam.getProjectId(), queryParam.getFieldId());
        if (CollUtil.isEmpty(fieldIds)) {
            return null;
        } else {
            pageRecordDTO.setFieldIds(fieldIds);
        }
        if (StringUtils.isNotBlank(queryParam.getWord()) || !StringUtils.equals(NULL, queryParam.getWord())) {
            pageRecordDTO.setWord(queryParam.getWord());
        }
        return pageRecordDTO;
    }

    /**
     * grpc record转换为dto对象
     *
     * @param recordDO
     * @return
     */
    private RecordDetailDTO entityToDetailDTO(RecordDO recordDO) {
        RecordDetailDTO recordDetailDTO = new RecordDetailDTO();
        recordDetailDTO.setId(recordDO.getId());
        recordDetailDTO.setContent(recordDO.getContent());
        recordDetailDTO.setProjectId(recordDO.getProjectId());
        recordDetailDTO.setSentimentScore(recordDO.getSentiScore());
        recordDetailDTO.setWorktableId(recordDO.getWorkTableId());
        recordDetailDTO.setWorktableName(recordDO.getWorkName());
        recordDetailDTO.setCollectionId(recordDO.getCollectionId());
        recordDetailDTO.setSentiment(recordDO.getSenti());
        recordDetailDTO.setFieldId(recordDO.getFieldId());
        recordDetailDTO.setFieldName(recordDO.getFieldName());
        if (StringUtils.isNotBlank(recordDO.getRecordTime())) {
            try {
                recordDetailDTO.setTime(LocalDateTime.parse(recordDO.getRecordTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            } catch (Exception ex) {
                log.warn("原话记录recordId解析失败，recordId:{},recordTime：{}", recordDO.getId(), recordDO.getRecordTime());
            }
        }
        recordDetailDTO.setIndustryId(recordDO.getIndustryId());
        recordDetailDTO.setFlag(recordDO.getRecordFlag());
        recordDetailDTO.setSurveyId(recordDO.getSurveyId());
        recordDetailDTO.setCreatedDate(recordDO.getCreatedDate());
        recordDetailDTO.setCreatedId(recordDO.getCreatedId());
        recordDetailDTO.setUpdatedDate(recordDO.getUpdatedDate());
        recordDetailDTO.setUpdatedId(recordDO.getUpdatedId());
        return recordDetailDTO;
    }

    /**
     * 分页查询原话记录，dto转换方法，话
     *
     * @param list      原话记录list
     * @param topicInfo 题信息，格式：话题组名-话题名
     * @param projectId 文本分析项目id
     * @return
     * @author liheng
     */
    private List<RecordDetailDTO> entityToDetailList(PageDTO<RecordDO> list, String topicInfo, String projectId) {
        List<String> ids = list.getData().stream().map(RecordDO::getId).collect(Collectors.toList());
        List<JoinInfoViewpointDO> joinInfos = joinInfoDao.listJoinInfos(projectId, ids);
        Map<String, List<JoinInfoViewpointDO>> collect = joinInfos.stream().collect(Collectors.groupingBy(JoinInfoViewpointDO::getRecordId));
        List<RecordDetailDTO> recordDetailDTOS = new ArrayList<>(list.getData().size());
        for (int i = 0; i < list.getData().size(); i++) {
            RecordDO recordDO = list.getData().get(i);
            RecordDetailDTO recordDetailDTO = entityToDetailDTO(recordDO);
            List<JoinInfoViewpointDO> viewpointList = collect.get(recordDO.getId());
            // 填充观点数据
            if (CollUtil.isNotEmpty(viewpointList)) {
                List<ViewInfoDTO> viewInfoDTOS = new ArrayList<>();
                for (int u = 0; u < viewpointList.size(); u++) {
                    JoinInfoViewpointDO viewpoint = viewpointList.get(u);
                    if (viewpoint.getViewSenti() != -2) {
                        ViewInfoDTO viewInfoDTO = new ViewInfoDTO(viewpoint.getViewId(), viewpoint.getRowContent(), viewpoint.getViewSenti(), viewpoint.getViewContent());
                        viewInfoDTOS.add(viewInfoDTO);
                    }
                }
                recordDetailDTO.setViews(viewInfoDTOS);
            }

            recordDetailDTO.setTopicInfo(topicInfo);
            recordDetailDTOS.add(recordDetailDTO);
        }
        return recordDetailDTOS;
    }
}
